package com.edu.atams.controller;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.edu.atams.common.dto.VotingStatistics;
import com.edu.atams.common.lang.Result;
import com.edu.atams.entity.Class;
import com.edu.atams.entity.*;
import com.edu.atams.mapper.SysUserMapper;
import com.edu.atams.mapper.VotingMapper;
import com.edu.atams.security.AccountUser;
import com.edu.atams.service.*;
import com.edu.atams.utils.AsyncRequestUtil;
import com.edu.atams.utils.WeChatUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author czj666
 * @since 2021-10-09
 */
@RestController
@RequestMapping("/voting")
public class VotingController extends BaseController {

    @Autowired
    SysUserMapper sysUserMapper;

    @Autowired
    SysUserService sysUserService;

    @Autowired
    VotingService votingService;

    @Autowired
    StudentClassService studentClassService;

    @Autowired
    StudentService studentService;

    @Autowired
    VotingClassService votingClassService;

    @Autowired
    TeacherService teacherService;

    @Autowired
    ParentService parentService;

    @Autowired
    VotingPhotoService votingPhotoService;

    @Autowired
    VotingOptionService votingOptionService;

    @Autowired
    VotingReportService votingReportService;

    @Autowired
    VotingMapper votingMapper;

    @Autowired
    ClassService classService;

    @Autowired
    GradeService gradeService;

    @Autowired
    WeChatUtil weChatUtil;

    @Autowired
    AsyncRequestUtil asyncRequestUtil;

    private SysUser getSysUser(){
        String username = SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString();
        return sysUserService.getOne(new QueryWrapper<SysUser>().eq("username", username));
    }

    @GetMapping("/getOnGongingVotingByStudent")
    public Result getOnGongingVotingByStudent(){
        Student student = studentService.getOne(new QueryWrapper<Student>().eq("user_id", this.getSysUser().getId()));
        // 查询当前学生所处的班级
        int classId = studentClassService.getCurrentClassIdByStudentId(student.getId());
        // 查询所处班级的问卷，且是进行中的状态
        Page<Voting> page = votingService.page(getPage(),new QueryWrapper<Voting>()
                .inSql("id", "select voting_id from voting_class where class_id = " + classId)
                .gt("end_time", DateUtil.date())
                .orderByDesc("create_time")
        );
        // 根据发布账号的id查询名字+角色名称
        page.getRecords().forEach(voting -> voting.setPublisherName(
            sysUserService.getById(voting.getPublisherId()).getRoleType()==2?
                teacherService.getOne(new QueryWrapper<Teacher>().eq("user_id",voting.getPublisherId())).getName():
                parentService.getOne(new QueryWrapper<Parent>().eq("user_id",voting.getPublisherId())).getName()+"家长"
        ));
        return Result.succ(page);
    }

    @GetMapping("/getAllVotingByStudent")
    public Result getAllVotingByStudent(){
        Student student = studentService.getOne(new QueryWrapper<Student>().eq("user_id", this.getSysUser().getId()));
        // 查询当前学生所处的班级
        int classId = studentClassService.getCurrentClassIdByStudentId(student.getId());
        // 查询所处班级的问卷，且是进行中的状态
        Page<Voting> page = votingService.page(getPage(),new QueryWrapper<Voting>()
                .inSql("id", "select voting_id from voting_class where class_id = " + classId)
                .orderByDesc("create_time")
        );
        // 根据发布账号的id查询名字+角色名称
        page.getRecords().forEach(voting -> voting.setPublisherName(
                sysUserService.getById(voting.getPublisherId()).getRoleType()==2?
                        teacherService.getOne(new QueryWrapper<Teacher>().eq("user_id",voting.getPublisherId())).getName():
                        parentService.getOne(new QueryWrapper<Parent>().eq("user_id",voting.getPublisherId())).getName()+"家长"
        ));
        return Result.succ(page);
    }

    @GetMapping("/getOnGongingVotingDetailByStudent")
    public Result getOnGongingVotingDetailByStudent(int votingId){
        Voting voting = votingService.getById(votingId);
        voting.setPublisherName(sysUserService.getById(voting.getPublisherId()).getRoleType()==2?
                teacherService.getOne(new QueryWrapper<Teacher>().eq("user_id",voting.getPublisherId())).getName()+"教师":
                parentService.getOne(new QueryWrapper<Parent>().eq("user_id",voting.getPublisherId())).getName()+"家长");
        voting.setVotingPhotos(votingPhotoService.list(new QueryWrapper<VotingPhoto>().eq("voting_id",votingId)));
        voting.setVotingOptions(votingOptionService.list(new QueryWrapper<VotingOption>().eq("voting_id",votingId)));
        return Result.succ(voting);
    }

    @PostMapping("/fillInVoting")
    public Result fillInVoting(int votingId, String votingOptionId){
        VotingReport votingReport = new VotingReport();
        votingReport.setSubmitterId(this.getSysUser().getId());
        votingReport.setVotingId(votingId);
        votingReport.setVotingOptionId(votingOptionId);
        votingReport.setCreateTime(new Date());
        votingReportService.save(votingReport);
        return Result.succ("");
    }

    @GetMapping("/getOnGongingVotingByTeacher")
    public Result getOnGongingVotingByTeacher(){
        Page<VotingStatistics> page =  votingService.pageVotingDto(getPage(),
                new QueryWrapper<Voting>()
                .eq("publisher_id",this.getSysUser().getId())
                .gt("end_time",DateUtil.date())
                .orderByDesc("create_time")
        );
        for (VotingStatistics votingStatistics : page.getRecords()) {
            List<Class> classes = classService.list(new QueryWrapper<Class>().inSql("id", "select class_id from voting_class where voting_id = " + votingStatistics.getId()));
            classes.forEach(myClass -> {
                myClass.setGrade(gradeService.getById(myClass.getGradeId()));
            });
            votingStatistics.setClasses(classes);
            // 如果需要则再加上学生的家长数量
            int total = votingClassService.list(new QueryWrapper<VotingClass>().eq("voting_id", votingStatistics.getId()))
                    .stream().mapToInt(votingClass -> studentClassService.count(new QueryWrapper<StudentClass>().eq("class_id", votingClass.getClassId()))).sum();
            int commitNum = votingReportService.count(new QueryWrapper<VotingReport>().eq("voting_id",votingStatistics.getId()));
            int unCommitNum = total - commitNum;
            votingStatistics.setCommitNum(commitNum);
            votingStatistics.setUnCommitNum(unCommitNum);
        }
        return Result.succ(page);
    }

    @GetMapping("/getCommitterAndUnCommitterInformation/{votingId}")
    public Result getCommitterAndUnCommitterInformation(@PathVariable int votingId){
        List<Integer> unCommitterIds = studentClassService.list(new QueryWrapper<StudentClass>()
                .inSql("class_id", "select class_id from voting_class where voting_id = " + votingId))
                .stream().map(StudentClass::getStudentId).collect(Collectors.toList());
        List<Integer> committerIds = votingReportService.list(new QueryWrapper<VotingReport>().eq("voting_id",votingId))
                .stream().map(VotingReport::getSubmitterId).collect(Collectors.toList());
        unCommitterIds.removeAll(committerIds);
        List<Student> committerInfo = committerIds.size()==0 ? null : studentService.list(new QueryWrapper<Student>().in("id",committerIds).select("id","name","photo"));
        List<Student> unCommitterInfo = unCommitterIds.size()==0 ? null : studentService.list(new QueryWrapper<Student>().in("id",unCommitterIds).select("id","name","photo"));
        return Result.succ(
                MapUtil.builder()
                        .put("committerInfo",committerInfo)
                        .put("unCommitterInfo",unCommitterInfo)
                        .build()
        );

    }

    @PostMapping("/save")
    public Result save(@RequestBody Voting voting){
        // 将问卷投票信息进行保存
        voting.setPublisherId(this.getSysUser().getId());
        voting.setCreateTime(new Date());
        votingService.saveInfo(voting);

        // 进行消息推送通知
        // 查询所有班级中的所有学生的账户绑定的openid,进行消息通知
        List<Integer> classIds = voting.getClasses().stream().map(Class::getId).collect(Collectors.toList());
        // 如果需要则再加上家长的openid
        List<String> openIds = sysUserMapper.getStudentOpenIdsByClassIds(classIds);
        // 这里默认就是直接查教师表了，不管家长能发布问卷了
        voting.setPublisherName(teacherService.getOne(new QueryWrapper<Teacher>().eq("user_id",voting.getPublisherId())).getName());
        asyncRequestUtil.sendVotingNotice(openIds,voting);
        return Result.succ("");
    }

    /**
     * 用于教师重新编辑的信息回显
     * @param votingId
     * @return
     */
    @GetMapping("/edit/{votingId}")
    public Result edit(@PathVariable Integer votingId){
        Voting voting = votingService.getById(votingId);
        voting.setVotingPhotos(votingPhotoService.list(new QueryWrapper<VotingPhoto>().eq("voting_id",votingId)));
        voting.setVotingOptions(votingOptionService.list(new QueryWrapper<VotingOption>().eq("voting_id",votingId)));
        return Result.succ(voting);
    }

    @PostMapping("/update")
    public Result update(@RequestBody Voting voting){
        votingService.update(new UpdateWrapper<Voting>()
            .set("title",voting.getTitle())
            .set("content",voting.getContent())
            .set("is_multiple",voting.getIsMultiple())
            .set("is_anonymous",voting.getIsAnonymous())
            .eq("id",voting.getId())
        );

        // 选项，图片全部删除，重新保存   --要不然就得去判断三种情况，修改？删除？增加？ 2*2*2
        votingOptionService.remove(new QueryWrapper<VotingOption>().eq("voting_id",voting.getId()));
        votingPhotoService.remove(new QueryWrapper<VotingPhoto>().eq("voting_id", voting.getId()));
        votingReportService.remove(new QueryWrapper<VotingReport>().eq("voting_id",voting.getId()));

        voting.getVotingOptions().forEach(vo -> vo.setVotingId(voting.getId()));
        votingOptionService.saveBatch(voting.getVotingOptions());
        voting.getVotingPhotos().forEach(vp -> vp.setVotingId(voting.getId()));
        votingPhotoService.saveBatch(voting.getVotingPhotos());
        return Result.succ("");
    }

    @PostMapping("/delete/{votingId}")
    public Result delete(@PathVariable Integer votingId){
        votingService.removeById(votingId);
        // 投票选项删除
        votingOptionService.remove(new QueryWrapper<VotingOption>().eq("voting_id",votingId));
        // 投票的图片删除
        List<VotingPhoto> votingPhotos = votingPhotoService.list(new QueryWrapper<VotingPhoto>().eq("voting_id", votingId));
        votingPhotoService.removeByIds(votingPhotos.stream().map(VotingPhoto::getId).collect(Collectors.toList()));
        this.deleteVotingPhoto(votingPhotos.stream().map(VotingPhoto::getUrl).collect(Collectors.toList()));
        // 删除对应的班级能看到的
        votingClassService.remove(new QueryWrapper<VotingClass>().eq("voting_id",votingId));
        // 删除填写记录
        votingReportService.remove(new QueryWrapper<VotingReport>().eq("voting_id",votingId));
        return Result.succ("");
    }


    public void deleteVotingPhoto(List<String> urls){
        String basePath = System.getProperty("user.dir") + "/files/";  // 定于文件上传的根路径
        List<String> fileNames = FileUtil.listFileNames(basePath);  // 获取所有的文件名称
        for (String url : urls) {
            String flag = url.split("files")[1].substring(1);
            String fileName = fileNames.stream().filter(name -> name.contains(flag)).findAny().orElse("");
            System.out.println(fileName);
            new File(basePath + fileName).delete();
        }
    }

    // 小程序只有选择图片wx.chooseImage()返回文件地址，然后才使用接口wx.uploadFile()将文件地址转为二进制，
    // 目前只知道只能一张一张上传，所以当发布问卷时，先一个一个图片保存，然后将其地址返回，等会再将图片地址与对应问卷投票id进行关联保存
    /*@PostMapping("/uploadVotingPhoto")
    public Result uploadVotingPhoto(MultipartFile votingPhoto, HttpServletRequest request){
        String filePath = "";
        String realPath = request.getSession().getServletContext().getRealPath("/uploadFile/");
        System.out.println(realPath);
        File directory = new File(realPath);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        try {
            String fileName = votingPhoto.getOriginalFilename();
            String suffix = fileName.substring(fileName.lastIndexOf("."));
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String filename = uuid + suffix;
            votingPhoto.transferTo(new File(realPath + filename));
            filePath = request.getScheme() + "://" +
                    request.getServerName() + ":"
                    + request.getServerPort()
                    + "/uploadFile/" + filename;
        } catch (Exception e) {
            // TODO
        }
        System.out.println(filePath);
        return Result.succ(filePath);
    }*/

}
